// ListCtrlSubclass.cpp: implementation of the CListCtrlSubclass class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "ListCtrlSubclass.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

COLORREF CListCtrlSubclass::m_crFrmNor = RGB(100, 100, 100);
COLORREF CListCtrlSubclass::m_crFrmFoc = RGB(0, 0, 255);
COLORREF CListCtrlSubclass::m_crBackNor = RGB(240, 240, 255);
COLORREF CListCtrlSubclass::m_crBackFoc = RGB(255, 255, 255);

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CListCtrlSubclass::CListCtrlSubclass()
{

}

CListCtrlSubclass::~CListCtrlSubclass()
{

}

LRESULT CListCtrlSubclass::WindowProc(UINT msg, WPARAM wp, LPARAM lp)
{
	switch (msg){
		case WM_PAINT:
			OnPaint();
			return 0;
		case WM_NCPAINT:
			CWndSubclass::WindowProc(msg, wp, lp);
			OnNcPaint();
			return 0;
		case WM_SETFOCUS:
			CWndSubclass::WindowProc(msg, wp, lp);
			OnNcPaint();
			return 0;
		case WM_KILLFOCUS:
			CWndSubclass::WindowProc(msg, wp, lp);
			OnNcPaint();
			return 0;
	}
	return CWndSubclass::WindowProc(msg, wp, lp);
}

void CListCtrlSubclass::OnNcPaint()
{
	CPaintDC dcWin(m_hWndHooked);
	dcWin.SetBkMode(TRANSPARENT);

	CRect rcWin;
	GetWindowRect(m_hWndHooked, &rcWin);
	rcWin -= rcWin.TopLeft();

	if (::GetFocus() == m_hWndHooked)
	{
		CRect rcLeftFrm(rcWin);
		rcLeftFrm.right = rcLeftFrm.left + 2;
		dcWin.Draw3dRect(&rcLeftFrm, RGB(160, 180, 200), RGB(100, 120, 140));

		CRect rcTopFrm(rcWin);
		rcTopFrm.bottom = rcTopFrm.top + 2;
		dcWin.Draw3dRect(&rcTopFrm, RGB(160, 180, 200), RGB(100, 120, 140));

		CRect rcRightFrm(rcWin);
		rcRightFrm.left = rcRightFrm.right - 2;
		dcWin.Draw3dRect(&rcRightFrm, RGB(100, 120, 140), RGB(160, 180, 200));

		CRect rcBottomFrm(rcWin);
		rcBottomFrm.top = rcBottomFrm.bottom - 2;
		dcWin.Draw3dRect(&rcBottomFrm, RGB(100, 120, 140), RGB(160, 180, 200));
	}
	else
	{
		/*CRect rcLeftFrm(rcWin);
		rcLeftFrm.right = rcLeftFrm.left + 2;
		dcWin.Draw3dRect(&rcLeftFrm, RGB(150, 150, 150), RGB(100, 100, 100));

		CRect rcTopFrm(rcWin);
		rcTopFrm.bottom = rcTopFrm.top + 2;
		dcWin.Draw3dRect(&rcTopFrm, RGB(150, 150, 150), RGB(100, 100, 100));

		CRect rcRightFrm(rcWin);
		rcRightFrm.left = rcRightFrm.right - 2;
		dcWin.Draw3dRect(&rcRightFrm, RGB(200, 200, 200), RGB(250, 250, 250));

		CRect rcBottomFrm(rcWin);
		rcBottomFrm.top = rcBottomFrm.bottom - 2;
		dcWin.Draw3dRect(&rcBottomFrm, RGB(200, 200, 200), RGB(250, 250, 250));*/
		CRect rcLeftFrm(rcWin);
		rcLeftFrm.right = rcLeftFrm.left + 2;
		dcWin.Draw3dRect(&rcLeftFrm, RGB(200, 200, 200), RGB(250, 250, 250));

		CRect rcTopFrm(rcWin);
		rcTopFrm.bottom = rcTopFrm.top + 2;
		dcWin.Draw3dRect(&rcTopFrm, RGB(200, 200, 200), RGB(250, 250, 250));

		CRect rcRightFrm(rcWin);
		rcRightFrm.left = rcRightFrm.right - 2;
		dcWin.Draw3dRect(&rcRightFrm, RGB(200, 200, 200), RGB(250, 250, 250));

		CRect rcBottomFrm(rcWin);
		rcBottomFrm.top = rcBottomFrm.bottom - 2;
		dcWin.Draw3dRect(&rcBottomFrm, RGB(200, 200, 200), RGB(250, 250, 250));
	}
}

BOOL BitBltTrans(HDC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight,
		HDC hdcSrc, int nXSrc, int nYSrc, DWORD dwRop, COLORREF crColorTrans)
{
	try{
		CDC dcMask;
		CBitmap btMask;
		dcMask.CreateCompatibleDC(CDCHandle(hdcDest));
		btMask.CreateBitmap(nWidth, nHeight, 1, 1,NULL);
		HBITMAP btOldMaskdcMask = dcMask.SelectBitmap(btMask.m_hBitmap);
		COLORREF crOldSrcBack = SetBkColor(hdcSrc, crColorTrans);
		BitBlt(dcMask.m_hDC, 0, 0, nWidth, nHeight, hdcSrc, 0, 0, SRCCOPY);
		BitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, SRCINVERT);
		BitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, dcMask.m_hDC, nXSrc, nXSrc, SRCAND);
		BitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, SRCINVERT); 

		dcMask.SelectBitmap(btOldMaskdcMask);
		SetBkColor(hdcSrc, crOldSrcBack);
	}catch(...){
		return FALSE;
	}
	return TRUE;
}

//? This is invlidate for changing bkcolor
void CListCtrlSubclass::OnPaint()
{
	CPaintDC dc(m_hWndHooked); 
	
	CRect rcClient;
	GetClientRect(m_hWndHooked, &rcClient);

	//CBrush brush(RGB(255, 255, 200));
	CBrush brush;
	//dc.FillRect(rcClient, &brush);		
	brush.DeleteObject();
	DoGradientFill(&dc, &rcClient);

	/*Paint in memory*/
	CDC memDC;
	memDC.CreateCompatibleDC(dc.m_hDC);	
	CBitmap bitmap;
	bitmap.CreateCompatibleBitmap(dc.m_hDC, rcClient.Width(), rcClient.Height());
	memDC.SelectBitmap((HBITMAP)bitmap);
	/*Fill background*/
	CBrush brushMem;
	//(RGB(255, 255, 255));
	brush.CreateSolidBrush((RGB(255, 255, 255));
	memDC.FillRect(rcClient, brushMem);		
	brush.DeleteObject();
	/*Call windows draw background and text*/
	memDC.SetBkColor(RGB(255, 255, 255));
	CWndSubclass::WindowProc(WM_PAINT, (WPARAM)memDC.m_hDC , 0);

	BitBltTrans(dc.m_hDC, 0, 0, rcClient.Width(), rcClient.Height(),
		memDC.m_hDC, rcClient.left, rcClient.top, SRCCOPY, RGB(255, 255, 255));
}

void CListCtrlSubclass::DoGradientFill(CDC *pDC, CRect* rect)
{
	CBrush brBk[64];
	int nWidth = rect->Width();	
	int nHeight = rect->Height();
	CRect rct;
	
	for (int i = 0; i < 64; i ++)
	{
		brBk[i].CreateSolidBrush(RGB(255 - (i / 3), 255 - (i / 3), 255 - (i / 5)));
	}
	
	for (i = rect->top; i <= nHeight + 2; i ++) 
	{
		rct.SetRect(rect->left, i, nWidth + 2, i + 1);
		pDC->FillRect(&rct, brBk[((i * 63) / nHeight)]);
	}
	
	for (i = 0; i < 64; i ++)
		brBk[i].DeleteObject();
}

